# Copyright 2009 UsableLabs
#
# This file is part of Katik.
#
# Katik is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Katik is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# Katik; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA  02111-1307 USA

import e32
import appuifw
import globalui
import contacts
import messaging
import inbox
import e32dbm

import time

sender_choices = [
        u'Anyone',
        u'Ones with suffix "Sender"',
        u'Ask me every time',
        ]

# functions
# --------------------------------------------------------------------

def safe_sms_send(address, s, attempt=5):
    while attempt > 0:
        try:
            messaging.sms_send(address, s)
            attempt = 0
        except:
            attempt = attempt - 1
            time.sleep(5)

def get_msg_address(ibox, msg_id):
    try:
        address = ibox.address(msg_id)
    except:
        address = None
    return address

def set_config(k, v):
    db = e32dbm.open(u'c:\\katik.db', 'c')
    db[k] = v
    db.reorganize()
    db.close()

def get_config(k, default=None):
    try:
        db = e32dbm.open(u'c:\\katik.db')
    except:
        db = None
    if db:
        v = db[k]
        db.close()
    else:
        v = default
    return v

def print_credit():
    print
    print u'Katik 0.10b'
    print u'Portable SMS Gateway'
    print u'Copyright (c) 2009 UsableLabs'
    print u'sponsored by'
    print u'Prince of Songkla University'
    print u'ThaiHealth Promotion Foundation'
    print

def print_note(msg, mtype='info'):
    print msg
    globalui.global_note(msg, mtype)

def process_waiting_messages():
    all_msg = ibox.sms_messages() # use global ibox
    all_msg.reverse()
    for msg_id in all_msg:
        process_message(msg_id)
    print u'waiting messages processed.'

def add_contact(ibox, msg_id, address):
    cdb = contacts.open()
    if not cdb.find(address):
        # add
        c = cdb.add_contact()
        c.add_field('mobile_number', address)
        c.add_field('last_name', address)
        c.commit()
        ibox.delete(msg_id)
        # notify
        print_note(u'%s added' % address)
        safe_sms_send(address, u'Hello %s' % address)
    if cdb.compact_required():
        cdb.compact()

def remove_contact(ibox, msg_id, address):
    cdb = contacts.open()
    clist = cdb.find(address)
    if clist:
        # del
        del cdb[clist[0].id]
        ibox.delete(msg_id)
        # notify
        print_note(u'%s removed.' % address)
        safe_sms_send(address, u'Good bye %s' % address)
    if cdb.compact_required():
        cdb.compact()

def relay_message(ibox, msg_id, msg, address):
    print u'begin relaying messages...'
    allowed = False
    cdb = contacts.open()
    clist = cdb.find(address)
    if clist:
        sender_cnf = get_config('sender', default='0')
        if sender_cnf == '0':
            allowed = True
        elif sender_cnf == '1':
            f = clist[0].find('suffix')
            if f and f[0].value == u'Sender':
                allowed = True
        elif sender_cnf == '2':
            if globalui.global_msg_query(msg, u'Forward this?', 0):
                allowed = True

    if allowed:
        for k in cdb:
            fl = cdb[k].find(type='mobile_number')
            if len(fl) > 0:
                safe_sms_send(fl[0].value, msg)
        print_note(u'message %s relayed.' % msg_id)
        ibox.delete(msg_id)
    else:
        print_note(u'message %s not allowed or not by allowed senders.' % msg_id)

# callbacks
# --------------------------------------------------------------------

def process_message(msg_id):
    ibox = inbox.Inbox()
    msg = ibox.content(msg_id)
    address = get_msg_address(ibox, msg_id)
    if not address:
        print_note(u'%s has no address. Ignored.' % msg_id)
        return

    if len(msg) >= 4 and msg[:4].lower() == 'join':
        add_contact(ibox, msg_id, address)
    elif len(msg) >= 5 and msg[:5].lower() == 'leave':
        remove_contact(ibox, msg_id, address)
    else:
        relay_message(ibox, msg_id, msg, address)

def set_sender():
    idx = appuifw.popup_menu(sender_choices, u'Who can send messages?')
    if idx != None:
        set_config('sender', unicode(idx))
        print_note(u'set senders to: %s' % sender_choices[idx], 'confirm')

def quit():
    print u'service stopped.'
    app_lock.signal()
    #appuifw.app.set_exit()

# main
# --------------------------------------------------------------------

appuifw.app.title = u'Katik'
appuifw.app.screen = 'normal'
appuifw.app.exit_key_handler = quit
appuifw.app.menu = [
        (u'Set Sender', set_sender),
        (u'Exit', quit),
        ]

print_credit()
ibox = inbox.Inbox()
process_waiting_messages()
ibox.bind(process_message)
print u'service started.'

try:
    sender_cnf = int(get_config('sender'))
except:
    sender_cnf = 0
print u'senders set to: %s' % sender_choices[sender_cnf]

app_lock = e32.Ao_lock()
app_lock.wait()

